#include "RadiationBarrel.h"

#include "GamePlayState.h"
#include "Time.h"
#include "Physics.h"
#include "Camera.h"

// Constructor
RadiationBarrel::RadiationBarrel(void)
{
	objectID = "Radiation Barrel";
}

// Destructor
RadiationBarrel::~RadiationBarrel(void)
{
}

// Update
void RadiationBarrel::Update(float deltaTime)
{
	isPushed = false;

	if(isActive == false)
		return;

	// Get a pointer to the player.
	Player* player = GamePlayState::GetInstance()->GetPlayer();

	// Get the player's hitbox.
	RECT pHitbox = player->GetHitBox();

	// Get the four corners and the center of the player.
	tVector2D topLeftPoint = { (float)pHitbox.left, (float)pHitbox.top };
	tVector2D topRightPoint = { (float)pHitbox.right, (float)pHitbox.top };
	tVector2D bottomLeftPoint = { (float)pHitbox.left, (float)pHitbox.bottom };
	tVector2D bottomRightPoint = { (float)pHitbox.right, (float)pHitbox.bottom };
	tVector2D playerCenterPoint = { 
		(float)pHitbox.left + ((pHitbox.right - pHitbox.left) >> 1), 
		(float)pHitbox.top + ((pHitbox.bottom - pHitbox.top) >> 1)
	};

	// Get the center of the radiation barrel.
	tVector2D centerPoint = { 
		(float)hitBox.left + ((hitBox.right - hitBox.left) >> 1), 
		(float)hitBox.top + ((hitBox.bottom - hitBox.top) >> 1)
	};

	center = centerPoint;

	// Calculate the lines to the player.
	tVector2D topLeftLine = topLeftPoint - centerPoint;
	tVector2D topRightLine = topRightPoint - centerPoint;
	tVector2D bottomLeftLine = bottomLeftPoint - centerPoint;
	tVector2D bottomRightLine = bottomRightPoint - centerPoint;
	tVector2D centerLine = playerCenterPoint - centerPoint;

	// Normalize the lines.
	topLeftLine = Vector2DNormalize(topLeftLine);
	topRightLine = Vector2DNormalize(topRightLine);
	bottomLeftLine = Vector2DNormalize(bottomLeftLine);
	bottomRightLine = Vector2DNormalize(bottomRightLine);
	centerLine = Vector2DNormalize(centerLine);

	vector<tVector2D> v;
	v.push_back(topLeftLine);
	v.push_back(topRightLine);
	v.push_back(bottomLeftLine);
	v.push_back(bottomRightLine);
	v.push_back(centerLine);

	player->DeactivateToolsFromRadiation(false);

	LinecastInfo hitInfo;
	bool didHitObject = false;
	for(unsigned int i = 0; i < v.size(); ++i)
	{
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, v[i], this);

		// Did the linecast hit an object?
		if(didHitObject == true)
		{
			dist = Vector2DLength(hitInfo.point - center);

			// Was it the player that the linecast hit?
			if(hitInfo.HitObject == player)
			{
				// Disable the player's tools.
				player->DeactivateToolsFromRadiation(true);
			}
		}
	}

#pragma region UNUSED CODE
	// Only perform one of the linecasts per frame.
	/*switch(Time::GetInstance().TotalFrames() % 5)
	{
	case 0:
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, topLeftLine, GetObjectID().c_str());
		direction = topLeftLine;
		break;
	case 1:
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, topRightLine, GetObjectID().c_str());
		direction = topRightLine;
		break;
	case 2:
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, bottomLeftLine, GetObjectID().c_str());
		direction = bottomLeftLine;
		break;
	case 3:
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, bottomRightLine, GetObjectID().c_str());
		direction = bottomRightLine;
		break;
	case 4:
		didHitObject = Physics::LineCast(hitInfo, range, centerPoint, centerLine, GetObjectID().c_str());
		direction = centerLine;
		break;
	default:
		break;
	}*/
#pragma endregion

	// Fall down.
	SetPosY(GetPosY() + Physics::GetGravity() * deltaTime);

	Physics::UpdateColRect(hitBox, (int)(positionX), (int)(positionY));
}

// Render
void RadiationBarrel::Render(void) const
{
	if(isActive == false)
		return;

	GameObject::Render();	
}

// HandleCollision
void RadiationBarrel::HandleCollision(GameObject& other, CollisionInfo& info)
{
	if(GamePlayState::GetInstance()->GetPlayer()->GetToolManager()->GetMag().GetAttched() == this)
		return;

	if(isActive == false)
		return;
	if(other.GetObjectID() == "Player" || other.GetObjectID() == "Ice" || other.GetObjectID() == "Moving Platform")
		return;

}

// ResetToCheckPoint
void RadiationBarrel::ResetToCheckPoint()
{

}

// SetRange
//	- Sets the maximum distance the radiation barrel will have
//	  an effect on the player.
void RadiationBarrel::SetRange(float range)
{
	this->range = range;
}

int RadiationBarrel::Push(CollisionSide side, int amtToMove)
{
	isPushed = true;

	LinecastInfo castInfo;
	tVector2D castStart;
	tVector2D castStartVert;
	tVector2D direction;
	switch(side)
	{
	case LEFT:
		castStart.fX = (float)hitBox.right;
		castStart.fY = positionY + (hitBox.bottom - hitBox.top)/2;
		point  = castStart;
		distance = amtToMove;
		direction.fX = 1;
		direction.fY = 0;

		if(Physics::LineCast(castInfo, (float)amtToMove, castStart, direction, "Radiation Barrel"))
		{
			int amtCanMove = (int)castInfo.Distance;
			positionX += amtCanMove + 4;
			return amtCanMove;
		}
		else
		{
			positionX += amtToMove + 4;
			return amtToMove;
		}
		break;
	case RIGHT:
		castStart.fX = (float)hitBox.left;
		castStart.fY = positionY + (hitBox.bottom - hitBox.top)/2;
		direction.fX = -1;
		direction.fY = 0;
		if(Physics::LineCast(castInfo, (float)amtToMove, castStart,direction, "Radiation Barrel"))
		{
			int amtCanMove = (int)castInfo.Distance;
			positionX -= amtCanMove + 4;
			return amtCanMove;
		}
		else
		{
			positionX -= amtToMove + 4;
			return amtToMove;
		}
		break;
	case TOP:
		castStart.fX = positionX + (hitBox.right - hitBox.left);
		castStartVert.fX = positionX;
		castStart.fY = (float)castStartVert.fY = (float)hitBox.top;
		direction.fX = 0;
		direction.fY = -1;
		if(Physics::LineCast(castInfo, (float)amtToMove, castStart,direction, "Radiation Barrel") || Physics::LineCast(castInfo, (float)amtToMove, castStartVert,direction, "Radiation Barrel"))
		{
			int amtCanMove = (int)castInfo.Distance;
			positionY += amtCanMove + 1;
			return amtCanMove;
		}
		else
		{
			positionY += amtToMove + 1;
			return amtToMove;
		}
		break;
	case BOTTOM:
		{
			positionY -= amtToMove+ 1;
			return amtToMove;
		}
		break;
	}
	return 0;
}